import os.path
from pytube import YouTube
import uuid

from app.sql_app import models
from app.sql_app.database import get_db_return
from main import cel
from tasks.utils import path_create, download_m3u8_video, convert_ts_to_mp4, get_html_by_selenium, \
    analysis_youtube_page_source_video_ids

BASE_PATH = "saves"
CATCH_PATH = "catch"


# @cel.task
# def crawl_video_with_no_sound(uri: str, filename: str, time_: int, tags: str):  # time_: 视频时长，单位：秒
#     if not filename:
#         filename = str(uuid.uuid4())
#     path_create(BASE_PATH)
#     cap = cv2.VideoCapture(uri)
#
#     # Define the codec and create VideoWriter object
#     # fourcc = cv2.VideoWriter_fourcc(*'XVID')
#     fourcc = cv2.VideoWriter_fourcc(*'mp4v')
#     out = cv2.VideoWriter(f'{BASE_PATH}/{filename}-{tags}-{time_}-{int(time.time())}.mp4', fourcc, 30.0, (1920, 1080))
#
#     while cap.isOpened():
#         ret, frame = cap.read()
#         if ret:
#             # frame = cv2.flip(frame, 0)  # 翻转
#
#             # write the flipped frame
#             out.write(frame)
#
#             cv2.imshow('frame', frame)
#             if cv2.waitKey(1) & 0xFF == ord('q'):
#                 break
#         else:
#             break
#
#     # Release everything if job is finished
#     cap.release()
#     out.release()
#     cv2.destroyAllWindows()
#     return


@cel.task
def crawl_m3u8(uri: str, filename: str, resource_id: int = None):
    path_create(CATCH_PATH)
    path_create(BASE_PATH)
    ts_file_path = f"{CATCH_PATH}/{uuid.uuid4()}.ts"
    mp4_file_path = f'{BASE_PATH}/{filename}'
    try:
        download_m3u8_video(uri, ts_file_path)
        if not os.path.exists(mp4_file_path):
            convert_ts_to_mp4(ts_file_path, mp4_file_path)
        else:
            print(f"注意：爬取了一个已经存在的文件: {mp4_file_path}，请检查代码逻辑")
        # os.remove(ts_file_path)  # 完成后删除缓存文件
    except Exception as e:
        print("crawl_m3u8 Exception: ", resource_id, e)


# @cel.task
# def crawl_m3u8_from_db():
#     crawl_log = []
#     db = get_db_return()
#     try:
#         models_resource_all = db.query(models.Resource).filter(
#             models.Resource.status == 0,
#             models.Resource.filetype == 0,
#             models.Resource.deleted == 0
#         ).all()
#         for item in models_resource_all:
#             if os.path.exists(f"{BASE_PATH}/{item.filename}"):
#                 item.status = 1
#                 db.commit()
#             else:
#                 res_id = crawl_m3u8.delay(item.uri, item.filename, item.id)
#                 crawl_log.append({
#                     "resource_id": str(item.id),
#                     "res_id": str(res_id)
#                 })
#         return {"success": True, "crawl_log": crawl_log}
#     finally:
#         db.close()


@cel.task
def zip_and_lock_resource():
    zip_filename = 'test01.zip'
    password = "12345678"
    source_path = ''
    os.system(f"7z a -tzip {zip_filename} -p{password} {source_path}")


@cel.task
def download_youtube(url: str):
    db = get_db_return()
    models_resource = db.query(models.Resource).filter(
        models.Resource.url == url
    ).first()
    if not models_resource:
        models_resource = models.Resource(filetype=1, url=url)
        db.add(models_resource)
    try:
        yt = YouTube(url)
        yt.streams.filter(progressive=True)
        stream = yt.streams.get_by_itag(22)
        if stream:
            stream.download(BASE_PATH)
            models_resource.status = 1
            models_resource.uri = stream.url
            models_resource.filename = stream.default_filename
            models_resource.title = yt.title
            models_resource.size = stream.filesize_mb
            models_resource.summary = yt.description[0:2999] if yt.description else None
            models_resource.keywords = str(yt.keywords)
            models_resource.views = yt.views
            models_resource.video_id = yt.video_id
            models_resource.publish_date = yt.publish_date
        else:
            models_resource.status = 2
        db.commit()
    except Exception as e:
        models_resource.status = 2
        db.commit()
        raise e
    finally:
        db.close()


@cel.task
def download_youtube_trigger(deep: int = 0):
    crawl_log = []
    db = get_db_return()
    try:
        models_resource_all = db.query(models.Resource).filter(
            models.Resource.status == 0,
            models.Resource.filetype == 1,
            models.Resource.deleted == 0,
            models.Resource.deep == deep
        ).all()
        for item in models_resource_all:
            res_id = download_youtube.delay(url=item.url)
            crawl_log.append({
                "resource_id": str(item.id),
                "res_id": str(res_id)
            })
        return {"success": True, "crawl_log": crawl_log}
    finally:
        db.close()


@cel.task
def crawl_youtube_page_save_video_ids(base_youtube_url: str, partition_: str, deep: int = 0, parent_url=None):
    page_html = get_html_by_selenium(base_youtube_url)
    video_ids = analysis_youtube_page_source_video_ids(page_html)
    db = get_db_return()
    try:
        for video_id in video_ids:
            models_first = db.query(models.Resource).filter(models.Resource.video_id == video_id).first()
            if not models_first:
                resource = models.Resource(
                    url=f"https://www.youtube.com/watch?v={video_id}",
                    filetype=1,
                    video_id=video_id,
                    partition_=partition_,
                    deep=deep,
                    parent_url=parent_url
                )
                db.add(resource)
        db.commit()
        return {"success": True}
    finally:
        db.close()


@cel.task
def crawl_next_deep_youtube_page_save_video_ids(deep: int = 0, partition_: str = None):
    db = get_db_return()
    try:
        query = db.query(models.Resource).filter(
            models.Resource.deep == deep,
            models.Resource.filetype == 1
        )
        if partition_:
            query = query.filter(models.Resource.partition_ == partition_)
        for item in query.all():
            crawl_youtube_page_save_video_ids.delay(
                base_youtube_url=item.url,
                partition_=item.partition_,
                deep=item.deep+1,
                parent_url=item.url
            )
        return {"success": True}
    finally:
        db.close()
